using System;
using System.Collections.Generic;

namespace DL
{
    
    /// <summary>
    /// 黑板系统
    /// </summary>
    public class GameBlackboard
    {
        private Dictionary<string, GameBlackboardKey> m_KeyRegistry = new();
        private Dictionary<GameBlackboardKey, object> m_Emtries = new Dictionary<GameBlackboardKey, object>();

        public List<Action> PassedActions { get; } = new();

        public void AddAction(Action action)
        {
            if (action != null)
            {
                PassedActions.Add(action);
            }
        }
        public void ClearActions() =>  PassedActions.Clear();

        public void Debug()
        {
            foreach (var entry in m_Emtries)
            {
                var entryType = entry.Value.GetType();

                if (entryType.IsGenericType && entryType.GetGenericTypeDefinition() == typeof(BlackboardEntry<>))
                {
                    var valueProperty = entryType.GetProperty("Value");
                    if (valueProperty == null) continue;

                    var value = valueProperty.GetValue(entry.Value);
                    UnityEngine.Debug.Log($"Key:{entry.Key},Value:{value}");
                }
            }
        }

        public GameBlackboardKey GetOrRegistry(string keyName)
        {
            if (string.IsNullOrEmpty(keyName))
            {
                UnityEngine.Debug.LogError("keyName is NullOrEmpty!");
                return new();
            }

            if (!m_KeyRegistry.TryGetValue(keyName, out var hash))
            {
                hash = new GameBlackboardKey(keyName);
                m_KeyRegistry.Add(keyName, hash);
            }
            return hash;
        }

        public bool ContainsKey(GameBlackboardKey key) => m_Emtries.ContainsKey(key);
        
        public bool Remove(GameBlackboardKey key) => m_Emtries.Remove(key);
        
        public bool TryGetValue<T>(GameBlackboardKey key, out T value)
        {
            if (m_Emtries.TryGetValue(key, out var entry) && entry is BlackboardEntry<T> castedEntry)
            {
                value = castedEntry.Value;
                return true;
            }
            
            value = default;
            return false;
        }

        public void SetValue<T>(GameBlackboardKey key, T value)
        {
            m_Emtries[key] = new BlackboardEntry<T>(key, value);
        }
    }
}
